package advancedpart.assignmentA2;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

import shared.*;

import java.util.HashMap;

/**
 * Programming workshop advanced part assignment 2
 * 
 * Methods for creating hashtables for textfiles and search for 
 * a given word:
 * 
 */
public class SearcherA2 {

	/**
	 * exists check if a word is present in a map.
	 * 
	 * @param map the data set
	 * @param word the word to search for
	 * @return true if the word is found
	 */
	public static boolean exists(HashMap<String, WordList> map, String word) {

		// Search for word in array	
		WordList currentWordList = map.get(word);

		// If the word is found
		if (currentWordList != null){
			return true;
		}

		// Word not found
		return false;
	}

	/**
	 * getUrlsForOneWord finds the urls where a word in the data 
	 * set i appear
	 * 
	 * @param map the data set
	 * @param word the word
	 * @return a string with the urls where the word is found
	 */
	public static String getUrlsForOneWord(HashMap<String, WordList> map, String word) {		 

		// Search for word in array
		WordList currentWordList = map.get(word);

		//Create variable for the returned urls
		String urls = "";

		//Check if the word exists, so null pointer exceptions are avoided
		if (currentWordList != null){	

			//Get the url linked list
			URLList currentURLList = currentWordList.nexturl;

			//Iterate through the list
			while (currentURLList != null) {
				//Print the current url
				urls += currentURLList.str + "\n";

				//Get the next url
				currentURLList = currentURLList.nexturl;
			}
		}		 	

		//Return the urls as a string
		return urls;
	}

	/**
	 * getUrlsFortowWords searches through a hash map for 2 word 
	 * Strings using a search operator. The operator is specified 
	 * with a SearchOperator enum and can be either AND or OR.
	 * A precondition for this method is that both words are in 
	 * the data set. Use Searcher.exists to evaluate that.
	 * 
	 * @param map the data set
	 * @param word1 the first word String to search for
	 * @param word2 the second word String to search for
	 * @param operator the operator. Specified with a SearchOperator enum
	 * @return
	 */
	public static String getUrlsForTwoWords(HashMap<String, WordList> map, String word1, String word2, SearchOperator operator)
	{
		//A precondition is the words are in the HashMap.
		String urls = "";

		//Get the first words urls
		WordList wordList1 = map.get(word1);
		URLList word1urlList = wordList1.nexturl;

		//Get the second words urls
		WordList wordList2 = map.get(word2);
		URLList word2urlList = wordList2.nexturl;

		//Check what algorithm to use depending on the operator
		switch(operator){
		case AND: 	
			//Iterate over the first list of urls
			while(word1urlList != null){

				//Reset the second list a every loop to ensure that every urls in the first list is checked against every url in the second list
				word2urlList = wordList2.nexturl;

				//Iterate over the second list of urls
				while(word2urlList != null){
					if (word1urlList.str.equalsIgnoreCase(word2urlList.str)){ //Check if the word is found i both url lists
						//Add url to string
						urls += word1urlList.str + "\n"; 
					}	

					//Get next element in the second list
					word2urlList = word2urlList.nexturl;
				}

				//Get next element in the first list
				word1urlList = word1urlList.nexturl;
			}
			break;

		case OR:
			//Iterate over the first list of urls
			while(word1urlList != null){

				//Add all urls from the first url list
				urls += word1urlList.str + "\n";

				//Get next element in the list
				word1urlList = word1urlList.nexturl;
			}

			//Iterate over the second url list
			while(word2urlList != null){

				//Variable for checking if the url is already added
				boolean exists = false;

				//Reset the first url list to ensure all urls are checked
				word1urlList = wordList1.nexturl;

				//Iterate over the first url list again
				while(word1urlList != null){

					//Check if the url is already added
					if (word1urlList.str.equalsIgnoreCase(word2urlList.str)){

						//Set variable if the url is added
						exists = true;

						//Break while loop
						break;
					}
					//Get next element in the first url list
					word1urlList = word1urlList.nexturl;
				}			

				//If the word isn't already added; add it
				if(!exists) urls += word2urlList.str + "\n";	

				//Get next element in the second url list
				word2urlList = word2urlList.nexturl;
			}
			break;

		default: 
			break;
		}

		//Return the found urls
		return urls;
	}




	/**
	 * createWordMap reads a text file and returns a HashMap where 
	 * each unique word String in the text file has an unique position 
	 * in the HashMap and a list of all the pages in the text file
	 * where it's found 
	 * 
	 * @param filename the file name and path of the file
	 * @return the map with the words
	 * @throws IOException
	 */
	public static HashMap<String, WordList> createWordMap(String filename) throws IOException {

		//Variables for constructing the HashMap
		String name; 
		String currentUrl = "";

		//Create the returned map
		HashMap<String, WordList> wordMap = new HashMap<String, WordList>();

		//Load the text file
		BufferedReader infile = new BufferedReader(new FileReader(filename));

		//Read the first line
		name = infile.readLine();
		
		// Iterate through lines
		while (name != null) {
			if ( !(name.startsWith("*PAGE")) ) {  //line contains word	
				
				//Get lower cased version of the word
				String nameLowerCased = name.toLowerCase();
				
				//Try the get the word in the HashMap
				WordList WordsAtKey = wordMap.get(nameLowerCased);							
				
				if (WordsAtKey != null) {// Check if words in map already
					if (WordsAtKey.nexturl.str != currentUrl ) { //Check if the url is already added										
						// Insert currentUrl as first HTLMURLList element in HTMLWordList
						WordsAtKey.nexturl = new URLList(currentUrl, WordsAtKey.nexturl);
					}																			
				} else { //If it's a new unique word
					// insert new WordList element with URLList element
					wordMap.put(nameLowerCased, new WordList(nameLowerCased, new URLList(currentUrl, null) , null));
				}							
			} else {  // line contains Url							
				currentUrl = name.substring(6);							 
			}						
			// read next line of file
			name = infile.readLine();
		}					

		//Return data set
		return wordMap;
	}	

}


